package com.cxj.g8llk;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.loon.framework.android.game.action.sprite.Sprites;
import org.loon.framework.android.game.core.LSystem;
import org.loon.framework.android.game.core.graphics.Screen;
import org.loon.framework.android.game.core.graphics.opengl.LTexture;

import android.util.Log;

public class Grids {
    private com.cxj.g8llk.Grid[][] grid;
    private int xBound;
    private int yBound;
    private Level levelInfo;
    int offsetX = 0;
    int offsetY = 0;
    private int pairsize;
    private int clearsize;
    private int stageNo;

    public Grids(int stageNo) {
        this.stageNo = stageNo;
        setStage(stageNo);
        this.xBound = levelInfo.getXBound() + 2;
        this.yBound = levelInfo.getYBound() + 2;
        this.grid = new Grid[yBound][xBound];
        this.clearsize = 0;
        this.pairsize = levelInfo.getXBound()*levelInfo.getYBound()/2;
    }
    
    public final void setStage(int no) {
        switch (no) {
        case 1:
            levelInfo = Level.Level1;
            break;
        case 2:
            levelInfo = Level.Level2;
            break;
        case 3:
            levelInfo = Level.Level3;
            break;
        case 4:
            levelInfo = Level.Level4;
            break;
        case 5:
            levelInfo = Level.Level5;
            break;
        default:
            levelInfo = Level.Level5;
            break;
        }
    }
    
    public boolean isClear()
    {
        return this.pairsize == clearsize;
    }
    
    public void incre() 
    {
        this.clearsize++;
    }

    public void init(Screen screen) {
        /**
         * 初始化一半Grid大小的數組，并隨機排列第二組
         * (0..(xB-2)*(yB-2))/2 generate
         * 
         * 
         */
        int gs = levelInfo.getXBound() * levelInfo.getYBound();
        int[] gss = new int[gs];
        int be = LSystem.getRandomBetWeen(0, gs - 1);
        for (int i = 0; i < gs / 2; i++) {
            int data = LSystem.getRandomBetWeen(0, 7);
            gss[be % gs] = data;
            gss[(be + gs / 2) % gs] = data;
            be++;
        }

        for (int y = 0; y < yBound; y++) {
            for (int x = 0; x < xBound; x++) {
                int data = 0;
                if (x == 0 || x == xBound - 1 || y == 0 || y == yBound - 1) {
                    grid[y][x] = new Grid(x, y, -1);
                    grid[y][x].setVisible(false);
                } else {
                    data = gss[(y - 1) * levelInfo.getXBound() + (x - 1)];
                    grid[y][x] = new Grid(x, y, data);
                    grid[y][x].setVisible(true);
                }

                LTexture img = RSL.one().getImage(data);
                int nx = offsetX + x * img.getWidth();
                int ny = offsetY + y * img.getHeight();

                grid[y][x].setImage(img);
                grid[y][x].setBorder(3);
                grid[y][x].setLocation(nx, ny);
                screen.getSprites().add(grid[y][x]);
            }
        }
    }

    public Grid getGrid(Screen screen, int x, int y) {
        Sprites ss = screen.getSprites();
        if (ss == null) {
            return null;
        }
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] instanceof Grid) {
                    Grid g = grid[i][j];
                    if (g.getCollisionBox().contains(x, y)) {
                        return g;
                    }
                }
            }
        }
        return null;
    }
    
    public boolean checkPath(Grid pre, Grid cur, LinkedList<Grid> pt) {
        Log.w("G8LLK", "priv is " + pre + ",curr is " + cur);
        if ((pre.getXpos() == cur.getXpos() && pre.getYpos() == cur.getYpos()) || pre.getData() != cur.getData()
                || pre.isPassable() || cur.isPassable()) {
            return false;
        }

        int ax = pre.getXpos() - 1;
        List axs = new ArrayList();
        axs.add(pre.getXpos());
        while (ax >= 0 && grid[pre.getYpos()][ax].isPassable()) {
            axs.add(ax);
            ax--;
        }

        ax = pre.getXpos() + 1;
        while (ax <= xBound - 1 && grid[pre.getYpos()][ax].isPassable()) {
            axs.add(ax);
            ax++;
        }

        int bx = cur.getXpos() - 1;
        List bxs = new ArrayList();
        bxs.add(cur.getXpos());
        while (bx >= 0 && grid[cur.getYpos()][bx].isPassable()) {
            bxs.add(bx);
            bx--;
        }

        bx = cur.getXpos() + 1;
        while (bx <= xBound - 1 && grid[cur.getYpos()][bx].isPassable()) {
            bxs.add(bx);
            bx++;
        }

        // 得到axs和bxs的交界
        List xs = new ArrayList();
        for (int i = 0; i < axs.size(); i++) {
            for (int j = 0; j < bxs.size(); j++) {
                if (axs.get(i).equals(bxs.get(j))) {
                    xs.add(axs.get(i));
                    break;
                }
            }
        }

        for (int i = 0; i < xs.size(); i++) {
            int min = (pre.getYpos() < cur.getYpos() ? pre.getYpos() : cur.getYpos()) + 1;
            int max = (pre.getYpos() < cur.getYpos() ? cur.getYpos() : pre.getYpos()) - 1;
            boolean pass = true;
            while (min <= max) {
                if (!grid[min][(Integer) xs.get(i)].isPassable()) {
                    pass = false;
                    break;
                }
                min++;
            }
            if (pass) {
                pt.add(pre);
                pt.add(new Grid((Integer) xs.get(i), pre.getYpos(), -1));
                pt.add(new Grid((Integer) xs.get(i), cur.getYpos(), -1));
                pt.add(cur);
                return true;
            }
        }

        int ay = pre.getYpos() - 1;
        List ays = new ArrayList();
        ays.add(pre.getYpos());
        while (ay >= 0 && grid[ay][pre.getXpos()].isPassable()) {
            ays.add(ay);
            ay--;
        }

        ay = pre.getYpos() + 1;
        while (ay <= yBound - 1 && grid[ay][pre.getXpos()].isPassable()) {
            ays.add(ay);
            ay++;
        }

        int by = cur.getYpos() - 1;
        List bys = new ArrayList();
        bys.add(cur.getYpos());
        while (by >= 0 && grid[by][cur.getXpos()].isPassable()) {
            bys.add(by);
            by--;
        }

        by = cur.getYpos() + 1;
        while (by <= yBound - 1 && grid[by][cur.getXpos()].isPassable()) {
            bys.add(by);
            by++;
        }

        // 得到axs和bxs的交界
        List ys = new ArrayList();
        for (int i = 0; i < ays.size(); i++) {
            for (int j = 0; j < bys.size(); j++) {
                if (ays.get(i).equals(bys.get(j))) {
                    ys.add(ays.get(i));
                    break;
                }
            }
        }

        for (int i = 0; i < ys.size(); i++) {
            int min = (pre.getXpos() < cur.getXpos() ? pre.getXpos() : cur.getXpos()) + 1;
            int max = (pre.getXpos() < cur.getXpos() ? cur.getXpos() : pre.getXpos()) - 1;
            boolean pass = true;
            while (min <= max) {
                if (!grid[(Integer) ys.get(i)][min].isPassable()) {
                    pass = false;
                    break;
                }
                min++;
            }
            if (pass) {
                pt.add(pre);
                pt.add(new Grid(pre.getXpos(), (Integer) ys.get(i), -1));
                pt.add(new Grid(cur.getXpos(), (Integer) ys.get(i), -1));
                pt.add(cur);
                return true;
            }
        }

        return false;// ok
    }

    public boolean findPath(LinkedList<Grid> pt) {
        for (int yi = 1; yi < grid.length - 1; yi++) {
            for (int xi = 1; xi < grid[yi].length - 1; xi++) {
                for (int yj = 1; yj < grid.length - 1; yj++) {
                    for (int xj = 1; xj < grid[yj].length - 1; xj++) {
                        if (this.checkPath(grid[yi][xi], grid[yj][xj], pt)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}
